#include <stdio.h>
#include <windows.h>

#ifdef _WIN32_CON_IO_H
#else
#define _WIN32_CON_IO_H
#ifdef __cplusplus
extern "C"{
#endif
HANDLE stdinHandle = NULL;
HANDLE stdoutHandle = NULL;
CONSOLE_SCREEN_BUFFER_INFO *outinfo = NULL;

void fillHandle()
{
    if (stdinHandle == NULL)
        stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
    if (stdoutHandle == NULL)
        stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
}

void fillInfo()
{
    fillHandle();
    if (outinfo == NULL){
        outinfo = malloc(sizeof(CONSOLE_SCREEN_BUFFER_INFO));
        GetConsoleScreenBufferInfo(stdoutHandle, outinfo);
    }
}

void repeat(char c, int t)
{
    while (t--){
        putchar(c);
    }
}

int clearScreen()
{
    system("cls");
}

int readChar()
{
    fillHandle();

    unsigned long read, mode;
    char c;

    GetConsoleMode(stdinHandle, &mode);
    SetConsoleMode(stdinHandle, 0);

    ReadConsole(stdinHandle, &c, 1, &read, 0);

    SetConsoleMode(stdinHandle, mode);
    
    return read == 1 ? c : -1;
}

size_t writeOneChar(char c, int x, int y)
{
    fillHandle();
    COORD co;
    co.X = x;
    co.Y = y;
    DWORD lp;
    WriteConsoleOutputCharacter(stdoutHandle, &c, 1, co, &lp);
    return lp;
}

size_t writeString(char *s, int x, int y)
{
    fillHandle();
    COORD co;
    co.X = x;
    co.Y = y;
    DWORD lp;
    DWORD len;
    len = strlen(s);
    WriteConsoleOutputCharacter(stdoutHandle, s, len, co, &lp);
    return lp;
}

size_t writeOneAttr(WORD attr, int x, int y)
{
    fillHandle();
    COORD co;
    co.X = x;
    co.Y = y;
    DWORD lp;
    WriteConsoleOutputAttribute(stdoutHandle, &attr, 1, co, &lp);
    return lp;
}

size_t getBufferWidth()
{
    fillInfo();
    return outinfo->dwSize.X;
}

size_t getBufferHeight()
{
    fillInfo();
    return outinfo->dwSize.Y;
}

size_t getWindowWidth()
{
    fillInfo();
    return outinfo->dwMaximumWindowSize.X;
}

size_t getWindowHeight()
{
    fillInfo();
    return outinfo->dwMaximumWindowSize.Y;
}
#ifdef __cplusplus
}
#endif
#endif
